home *** CD-ROM | disk | FTP | other *** search
/ Aminet 7 / Aminet 7 - August 1995.iso / Aminet / dev / gui / gengui2.lha / GenGui2 / lib / gengui_lnk.c next >
Encoding:
C/C++ Source or Header  |  1995-02-16  |  37.4 KB  |  1,403 lines

  1.  
  2. #include <stdlib.h>
  3.  
  4. #define __USE_SYSBASE
  5.  
  6. #include <exec/libraries.h>
  7. #include <exec/types.h>
  8. #include <proto/exec.h>
  9. #include <proto/gadtools.h>
  10. #include <libraries/gadtools.h>
  11. #include <proto/intuition.h>
  12. #include <intuition/intuition.h>
  13. #include <proto/graphics.h>
  14. #include <graphics/text.h>
  15. #include <string.h>
  16. #include <intuition/gadgetclass.h>
  17. #include <proto/layers.h>
  18. #include <proto/utility.h>
  19.  
  20. #include "gengui.h"
  21.  
  22. #define max(x,y) ((x)>(y)?(x):(y))
  23. #define min(x,y) ((x)<(y)?(x):(y))
  24.  
  25. ULONG Modify[]={0,0,GTCB_Checked,GTIN_Number,GTLV_Selected,
  26.                           GTMX_Active,0,GTCY_Active,GTPA_Color,
  27.                           GTSC_Top,0,GTSL_Level,GTST_String,0};
  28.  
  29. ULONG Default[]={0,0,FALSE,0,~0,0,0,0,1,0,0,0,(ULONG)"",0};
  30.  
  31. static ULONG *MergeTags(ULONG *oldlist,ULONG *newlist)
  32. /* oldlist enthält als ersten Eintrag die Länge des Arrays, genauso
  33.    die zurückgegebene Liste */
  34. {
  35.    ULONG *p;
  36.    if(!oldlist) {
  37.       oldlist=malloc(16*sizeof(ULONG));
  38.       if(!oldlist) return(NULL);
  39.       oldlist[0]=16;
  40.       oldlist[1]=TAG_DONE;
  41.    }
  42.  
  43.    while(*newlist!=TAG_DONE) {
  44.       switch(*newlist) {
  45.          case TAG_IGNORE:  newlist+=2;
  46.                            break;
  47.          case TAG_MORE:    newlist=(ULONG *)newlist[1];
  48.                            break;
  49.          case TAG_SKIP:    newlist+=2*newlist[1]+2;
  50.                            break;
  51.          default:
  52.  
  53.                            p=oldlist+1;
  54.  
  55.             /* passenden Eintrag in der Taglist suchen, bzw Ende der Liste */
  56.  
  57.                            while(*p!=TAG_DONE && *p!=*newlist) p+=2;
  58.  
  59.                            if(*p==*newlist) {
  60.                               p[1]=newlist[1]; /* alte Daten ueberschreiben */
  61.                               newlist+=2;
  62.                            } else {
  63.                               int n=p-oldlist; /* Position im Array; */
  64.  
  65.                               if(n>=oldlist[0]-1) { /* Array vergrößern */
  66.                                  ULONG *mem;
  67.                                  mem=realloc(oldlist,oldlist[0]+16*sizeof(ULONG));
  68.                                  if(!mem) return(NULL);
  69.                                  oldlist=mem;
  70.                                  oldlist[0]+=16;
  71.                                  p=oldlist+n;
  72.                               }
  73.  
  74.                               *p++=*newlist++;
  75.                               *p++=*newlist++;
  76.                               *p=TAG_DONE;
  77.                            }
  78.                            break;
  79.       }
  80.    }
  81.    return(oldlist);
  82. }
  83.  
  84. BOOL GG_SetGadgetAttrsA(struct Gadget *gad,struct Window *win,
  85.                        struct Requester *req, ULONG *Tag)
  86. {
  87.    ULONG *newtags;
  88.    struct GadInfo *gi;
  89.  
  90.    gi=GetInfo(gad);
  91.  
  92.    if(!gi->SaveTags) {
  93.       gi->SaveTags=MergeTags(NULL,gi->Tags);
  94.       if(!gi->SaveTags) return(FALSE);
  95.    }
  96.  
  97.    newtags=MergeTags(gi->SaveTags,Tag);
  98.    if(!newtags) return(FALSE);
  99.    gi->SaveTags=newtags;
  100.    GT_SetGadgetAttrsA(gad,win,req,(struct TagItem *)Tag);
  101.    return(TRUE);
  102. }
  103. BOOL GG_SetGadgetAttrs(struct Gadget *gad,struct Window *win,
  104.                        struct Requester *req, ULONG Tag1,...)
  105. {
  106.    return(GG_SetGadgetAttrsA(gad,win,req,&Tag1));
  107. }
  108.  
  109. BOOL GG_SetLowlevelAttrsA(struct GadInfo *gad, ULONG *Tag)
  110. {
  111.    ULONG *newtags;
  112.  
  113.    if(gad->Dim.Kind<0) return FALSE;
  114.  
  115.    if(!gad->SaveTags) {
  116.       gad->SaveTags=MergeTags(NULL,gad->Tags);
  117.       if(!gad->SaveTags) return(FALSE);
  118.    }
  119.  
  120.    newtags=MergeTags(gad->SaveTags,Tag);
  121.    if(!newtags) return(FALSE);
  122.    gad->SaveTags=newtags;
  123.    return(TRUE);
  124. }
  125. BOOL GG_SetLowlevelAttrs(struct GadInfo *gad, ULONG Tag1,...)
  126. {
  127.    return(GG_SetLowlevelAttrsA(gad,&Tag1));
  128. }
  129.  
  130. static int MakeGTGadget(struct WinInfo *winfo,                       /**/
  131.                             struct GadInfo *gad,
  132.                             int left, int top, int width, int height)
  133. {
  134.    struct NewGadget ng;
  135.  
  136.    if(winfo->Mode==GG_MODE_REFRESH && gad->Dim.Kind>=0) return(0);
  137.  
  138.    ng.ng_LeftEdge=left + (gad->Dim.XSpace>>1);
  139.    ng.ng_TopEdge=top + (gad->Dim.YSpace>>1);
  140.    ng.ng_Width=width - gad->Dim.XSpace;
  141.    ng.ng_Height=height - gad->Dim.YSpace;
  142.    ng.ng_GadgetText=gad->Text;
  143.    ng.ng_TextAttr=gad->TextAttr ? gad->TextAttr : &winfo->TextAttr;
  144.    ng.ng_GadgetID=gad->GadgetID;
  145.    ng.ng_Flags=gad->Flags;
  146.    ng.ng_VisualInfo=winfo->Visual;
  147.    ng.ng_UserData=(void *)gad;
  148.  
  149.    if(gad->Dim.Kind>=0) {
  150.       /* Falls dies kein erneutes aufsetzen ist: SaveTags neu errechnen */
  151.       if(!gad->SaveTags) { /* || (!(winfo->Box->Dim.Flags & GG_FLAG_BACKUP) && winfo->Mode==GG_MODE_NEW)) { */
  152.          ULONG *tags;
  153.          static ULONG modifytag[]={0,0,TAG_DONE};
  154.  
  155.          if(gad->SaveTags) free(gad->SaveTags);
  156.          gad->SaveTags=NULL;
  157.  
  158.          if(Modify[gad->Dim.Kind]) { /* Allocate savetags for use with GG_GetIMsg() */
  159.             modifytag[0]=Modify[gad->Dim.Kind];
  160.             modifytag[1]=Default[gad->Dim.Kind];
  161.             tags=MergeTags(NULL,modifytag);
  162.             if(!tags) return(1);
  163.             gad->SaveTags=tags;
  164.          }
  165.          tags=MergeTags(gad->SaveTags,gad->Tags);
  166.          if(!tags) return(1);
  167.          gad->SaveTags=tags;
  168.       }
  169.  
  170.       winfo->Prev=gad->ThisGad=winfo->Gadgets[gad->GadNum]=
  171.           CreateGadgetA(gad->Dim.Kind,winfo->Prev,&ng,(struct TagItem *)(gad->SaveTags+1));
  172.       if(winfo->Prev==NULL) return(1); else return(0);
  173.    } else {
  174.       return(gad->CustomFunc(winfo,&ng,gad,left,top,width,height));
  175.    }
  176. } /**/
  177.  
  178. void GG_GfxPrintSize(struct RastPort *rast,char *text,struct GG_ObjectSize *size)
  179. {
  180.    int x;
  181.    char *p;
  182.    struct RastPort rp;
  183.    struct TextExtent ext;
  184.  
  185.    rp=*rast;
  186.  
  187.    SetSoftStyle(&rp,FS_NORMAL,-1);
  188.  
  189.    size->Height=rp.Font->tf_YSize;
  190.    size->Width=0;
  191.  
  192.    x=0;
  193.  
  194.    for(p=text;*p;p++) {
  195.  
  196.       if(*p=='\n') {
  197.  
  198.          if(p-text>0) {
  199.             TextExtent(&rp,text,p-text,&ext);
  200.             x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  201.             if(x>size->Width) size->Width=x;
  202.             x=0;
  203.             size->Height+=rp.Font->tf_YSize;
  204.          }
  205.          text=p+1;
  206.  
  207.       } else if(*p=='%') {
  208.  
  209.          if(p[1]=='%') {
  210.             p++;
  211.             TextExtent(&rp,text,p-text,&ext);
  212.             x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  213.             text=p+1;
  214.  
  215.          } else {
  216.  
  217.             if(p-text>0) {
  218.                TextExtent(&rp,text,p-text,&ext);
  219.                x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  220.             }
  221.  
  222.             p++;
  223.  
  224.             switch(*p) {
  225.  
  226.                case 'C': p++; break;
  227.                case 'c': p++; break;
  228.  
  229.                case 'I': SetSoftStyle(&rp,FSF_ITALIC,FSF_ITALIC);break;
  230.                case 'i': SetSoftStyle(&rp,0,FSF_ITALIC);break;
  231.                case 'B': SetSoftStyle(&rp,FSF_BOLD,FSF_BOLD);break;
  232.                case 'b': SetSoftStyle(&rp,0,FSF_BOLD);break;
  233.                case 'U': SetSoftStyle(&rp,FSF_UNDERLINED,FSF_UNDERLINED);break;
  234.                case 'u': SetSoftStyle(&rp,0,FSF_UNDERLINED);break;
  235.  
  236.                case 'N': SetSoftStyle(&rp,FS_NORMAL,-1);break;
  237.  
  238.                default: break;
  239.             }
  240.  
  241.             text=p+1;
  242.          }
  243.       }
  244.    }
  245.  
  246.    if(p-text>0) {
  247.       TextExtent(&rp,text,p-text,&ext);
  248.       x+=ext.te_Extent.MaxX-ext.te_Extent.MinX+1;
  249.       if(x>size->Width) size->Width=x;
  250.    }
  251. }
  252. void GG_GfxPrint(struct RastPort *rast,char *text,int left,int top)
  253. {
  254.    struct RastPort rp;
  255.    int x;
  256.    char *p;
  257.  
  258.  
  259.    rp=*rast;
  260.  
  261.    SetDrMd(&rp,JAM2);
  262.    SetAPen(&rp,1);
  263.    SetBPen(&rp,0);
  264.    SetSoftStyle(&rp,FS_NORMAL,-1);
  265.  
  266.    top+=rp.Font->tf_Baseline;
  267.    x=left;
  268.  
  269.    for(p=text;*p;p++) {
  270.  
  271.       if(*p=='\n') {
  272.  
  273.          if(p-text>0) {
  274.             Move(&rp,x,top);
  275.             Text(&rp,text,p-text);
  276.             x=left;
  277.             top+=rp.Font->tf_YSize;
  278.          }
  279.          text=p+1;
  280.  
  281.       } else if(*p=='%') {
  282.  
  283.          if(p[1]=='%') {
  284.             p++;
  285.             Move(&rp,x,top);
  286.             Text(&rp,text,p-text);
  287.             x+=TextLength(&rp,text,p-text);
  288.             text=p+1;
  289.  
  290.          } else {
  291.  
  292.             if(p-text>0) {
  293.                Move(&rp,x,top);
  294.                Text(&rp,text,p-text);
  295.                x+=TextLength(&rp,text,p-text);
  296.             }
  297.  
  298.             p++;
  299.  
  300.             switch(*p) {
  301.  
  302.                case 'C': p++;SetAPen(&rp,*p-'0');break;
  303.                case 'c': p++;SetBPen(&rp,*p-'0');break;
  304.  
  305.                case 'I': SetSoftStyle(&rp,FSF_ITALIC,FSF_ITALIC);break;
  306.                case 'i': SetSoftStyle(&rp,0,FSF_ITALIC);break;
  307.                case 'B': SetSoftStyle(&rp,FSF_BOLD,FSF_BOLD);break;
  308.                case 'b': SetSoftStyle(&rp,0,FSF_BOLD);break;
  309.                case 'U': SetSoftStyle(&rp,FSF_UNDERLINED,FSF_UNDERLINED);break;
  310.                case 'u': SetSoftStyle(&rp,0,FSF_UNDERLINED);break;
  311.  
  312.                case 'N': SetSoftStyle(&rp,FS_NORMAL,-1);break;
  313.  
  314.                default: break;
  315.             }
  316.  
  317.             text=p+1;
  318.          }
  319.       }
  320.    }
  321.  
  322.    if(p-text>0) {
  323.       Move(&rp,x,top);
  324.       Text(&rp,text,p-text);
  325.    }
  326. }
  327.  
  328. static int MakePlainText(struct WinInfo *winfo,                      /**/
  329.                           struct GadInfo *gad,
  330.                           int left,int top,int width,int height)
  331. {
  332.    struct TextFont *newfont=NULL,*oldfont;
  333.  
  334.    if(!winfo->Render) return 0;
  335.  
  336.    if(gad->TextAttr) {
  337.       newfont=OpenFont(gad->TextAttr);
  338.       if(!newfont) return 1;
  339.  
  340.       oldfont=winfo->Window->RPort->Font;
  341.       SetFont(winfo->Window->RPort,newfont);
  342.    }
  343.  
  344.  
  345.    if(gad->Flags) {
  346.  
  347.       struct GG_ObjectSize size;
  348.  
  349.       GG_GfxPrintSize(winfo->Window->RPort,gad->Text,&size);
  350.  
  351.       width-=gad->Dim.XSpace;
  352.       height-=gad->Dim.YSpace;
  353.  
  354.       if(gad->Flags & GG_HCentered) {
  355.          left+=width-size.Width>>1;
  356.       } else if(gad->Flags & GG_Right) {
  357.          left+=width-size.Width;
  358.       }
  359.  
  360.       if(gad->Flags & GG_VCentered) {
  361.          top+=height-size.Height>>1;
  362.       } else if(gad->Flags & GG_Bottom) {
  363.          top+=height-size.Height;
  364.       }
  365.    }
  366.  
  367.    GG_GfxPrint(winfo->Window->RPort,gad->Text,left+(gad->Dim.XSpace>>1)
  368.                                           ,top+(gad->Dim.YSpace>>1));
  369.  
  370.    if(newfont) {
  371.       SetFont(winfo->Window->RPort,oldfont);
  372.       CloseFont(newfont);
  373.    }
  374.  
  375.    return 0;
  376.  
  377. }
  378. static int MakeGfxButton(struct WinInfo *winfo,                      /**/
  379.                           struct GadInfo *gad,
  380.                           int left,int top,int width,int height)
  381. {
  382.    struct Gadget *g;
  383.  
  384.    if(winfo->Mode != GG_MODE_NEW && winfo->Mode !=GG_MODE_RESIZE) return 0;
  385.  
  386.    width-=gad->Dim.XSpace;
  387.    height-=gad->Dim.YSpace;
  388.    left+=gad->Dim.XSpace>>1;
  389.    top+=gad->Dim.YSpace>>1;
  390.  
  391.    if(!gad->SaveTags && !(gad->SaveTags=calloc(1,sizeof(struct Gadget))))
  392.          return 1;
  393.  
  394.    g=(struct Gadget *)gad->SaveTags;
  395.  
  396.    g->LeftEdge=left;
  397.    g->TopEdge=top;
  398.    g->Width=width;
  399.    g->Height=height;
  400.  
  401.    if((gad->Flags ^ GG_FullSize) && gad->Tags[0]) {
  402.  
  403.       struct Image *i,*i2;
  404.  
  405.       i=(struct Image *)gad->Tags[0];
  406.       i2=(struct Image *)gad->Tags[1];
  407.  
  408.       if(gad->Flags & GG_HCentered) {
  409.          i->LeftEdge=width-i->Width>>1;
  410.          if(i2) i2->LeftEdge=width-i->Width>>1;
  411.       } else if(gad->Flags & GG_Right) {
  412.          i->LeftEdge=width-i->Width;
  413.          if(i2) i2->LeftEdge=width-i->Width;
  414.       }
  415.  
  416.       if(gad->Flags & GG_VCentered) {
  417.          i->TopEdge=height-i->Height>>1;
  418.          if(i2) i2->TopEdge=height-i->Height>>1;
  419.       } else if(gad->Flags & GG_Bottom) {
  420.          i->TopEdge=height-i->Height;
  421.          if(i2) i2->TopEdge=height-i->Height;
  422.       }
  423.  
  424.       if(!(gad->Flags & GG_FullSize)) {
  425.          g->LeftEdge=left+i->LeftEdge;
  426.          g->TopEdge=top+i->TopEdge;
  427.          g->Width=i->Width;
  428.          g->Height=i->Height;
  429.  
  430.          i->LeftEdge=0;
  431.          i->TopEdge=0;
  432.  
  433.          if(i2) {
  434.             i2->LeftEdge=0;
  435.             i2->TopEdge=0;
  436.          }
  437.       }
  438.  
  439.    }
  440.  
  441.    g->Flags=GFLG_GADGIMAGE
  442.                | (gad->Tags[0]&&gad->Tags[1]?GFLG_GADGHIMAGE:GFLG_GADGHCOMP);
  443.  
  444.    if(gad->Flags & GG_NoHighlight) g->Flags=GFLG_GADGHNONE|GFLG_GADGIMAGE;
  445.  
  446.    g->Activation=GACT_RELVERIFY;
  447.    g->GadgetType=GTYP_BOOLGADGET;
  448.  
  449.    g->GadgetRender=(void *)(gad->Tags[0]);
  450.    g->SelectRender=(void *)(gad->Tags[0]?gad->Tags[1]:0);
  451.  
  452.    g->GadgetID=gad->GadgetID;
  453.  
  454.    g->UserData=gad;
  455.  
  456.    winfo->Prev->NextGadget=g;
  457.    winfo->Prev=gad->ThisGad=winfo->Gadgets[gad->GadNum]=g;
  458.  
  459.    return 0;
  460. }
  461.  
  462. static int MakeGuiGadget(struct WinInfo *winfo,                      /**/
  463.                           struct Box *box,
  464.                           int left,int top,int width,int height)
  465. {
  466.    struct Box **p;
  467.    int relx,rely,absx,absy;
  468.    int w,h;
  469.  
  470.    if(box->Dim.Kind>0 || box->Dim.Kind==GG_CUSTOM_KIND)
  471.                          return(MakeGTGadget(winfo,(struct GadInfo *)box,
  472.                                                  left,top,width,height));
  473.  
  474.    if(box->Dim.Kind==GG_PLAINTEXT_KIND)
  475.                          return MakePlainText(winfo,(struct GadInfo *)box,
  476.                                               left,top,width,height);
  477.    if(box->Dim.Kind==GG_GFXBUTTON_KIND)
  478.                          return MakeGfxButton(winfo,(struct GadInfo *)box,
  479.                                               left,top,width,height);
  480.  
  481.    if(!winfo->Render) {
  482.       for(p=box->Entry;*p;p++) {
  483.          if(MakeGuiGadget(winfo,(*p),0,0,0,0)) return(1);
  484.       }
  485.    } else {
  486.  
  487.       if(box->Dim.Flags & (GG_FLAG_RAISED | GG_FLAG_RECESSED)) {
  488.  
  489.          if(box->Backfill) {
  490.             struct Hook *old;
  491.  
  492.             old=InstallLayerHook(winfo->Window->RPort->Layer,box->Backfill);
  493.             EraseRect(winfo->Window->RPort,left+(box->Dim.XSpace>>1),
  494.                                          top+(box->Dim.YSpace>>1),
  495.                                          left+(box->Dim.XSpace>>1)+width-box->Dim.XSpace-1,
  496.                                          top+(box->Dim.YSpace>>1)+height-box->Dim.YSpace-1);
  497.             InstallLayerHook(winfo->Window->RPort->Layer,old);
  498.          }
  499.  
  500.          DrawBevelBox(winfo->Window->RPort,
  501.                         left+(box->Dim.XSpace>>1),
  502.                         top+(box->Dim.YSpace>>1),
  503.                         width-box->Dim.XSpace,
  504.                         height-box->Dim.YSpace,
  505.                 (box->Dim.Flags & GG_FLAG_RAISED)?TAG_IGNORE:GTBB_Recessed,TRUE,
  506.                         GT_VisualInfo,winfo->Visual,
  507.                         TAG_DONE);
  508.  
  509.          left+=box->Dim.XSpace;
  510.          top+=box->Dim.YSpace;
  511.          width-=2*box->Dim.XSpace;
  512.          height-=2*box->Dim.YSpace;
  513.  
  514.       } else {
  515.          if(box->Backfill) {
  516.             struct Hook *old;
  517.  
  518.             old=InstallLayerHook(winfo->Window->RPort->Layer,box->Backfill);
  519.             EraseRect(winfo->Window->RPort,left,top,
  520.                                          left+width-1,
  521.                                          top+height-1);
  522.             InstallLayerHook(winfo->Window->RPort->Layer,old);
  523.          }
  524.  
  525.          if(box->Dim.Flags & GG_FLAG_BAR) {
  526.             struct DrawInfo *dinfo;
  527.             struct RastPort rast;
  528.  
  529.             rast=*winfo->Window->RPort;
  530.  
  531.             dinfo=GetScreenDrawInfo(winfo->Window->WScreen);
  532.  
  533.             if(box->Dim.Kind==GG_HBOX) {
  534.  
  535.                SetAPen(&rast,dinfo->dri_Pens[SHADOWPEN]);
  536.                Move(&rast,left,top);
  537.                Draw(&rast,left+width-1,top);
  538.  
  539.                SetAPen(&rast,dinfo->dri_Pens[SHINEPEN]);
  540.                Move(&rast,left,top+1);
  541.                Draw(&rast,left+width-1,top+1);
  542.  
  543.             } else {
  544.  
  545.                SetAPen(&rast,dinfo->dri_Pens[SHADOWPEN]);
  546.                Move(&rast,left,top);
  547.                Draw(&rast,left,top+height-1);
  548.  
  549.                SetAPen(&rast,dinfo->dri_Pens[SHINEPEN]);
  550.                Move(&rast,left+1,top);
  551.                Draw(&rast,left+1,top+height-1);
  552.  
  553.             }
  554.  
  555.             FreeScreenDrawInfo(winfo->Window->WScreen,dinfo);
  556.          }
  557.       }
  558.  
  559.       if(!box->Entry) return(0);
  560.  
  561.       relx=box->Dim.SRx;
  562.       rely=box->Dim.SRy;
  563.       absx=box->Dim.SPx;
  564.       absy=box->Dim.SPy;
  565.  
  566.       if(box->Dim.Kind==GG_HBOX) {
  567.  
  568.          width-=absx;
  569.          if(width<0) width=0;
  570.  
  571.          for(p=box->Entry;*p;p++) {
  572.             w=width * ((*p)->Dim.Rx)/relx + (*p)->Dim.Px;
  573.             h=height * ((*p)->Dim.Ry)/rely + (*p)->Dim.Py;
  574.  
  575.             if(MakeGuiGadget(winfo,(*p),left,top,w,h)) return(1);
  576.  
  577.             left+=w;
  578.          }
  579.  
  580.       } else if(box->Dim.Kind==GG_VBOX) {
  581.  
  582.          height-=absy;
  583.          if(height<0) height=0;
  584.  
  585.          for(p=box->Entry;*p;p++) {
  586.             w=width * ((*p)->Dim.Rx)/relx + (*p)->Dim.Px;
  587.             h=height * ((*p)->Dim.Ry)/rely + (*p)->Dim.Py;
  588.  
  589.             if(MakeGuiGadget(winfo,(*p),left,top,w,h)) return(1);
  590.  
  591.             top+=h;
  592.          }
  593.  
  594.       }
  595.    }
  596.    return(0);
  597. }          /**/
  598. static void FreeGuiGadget(struct Box *box)
  599. {
  600.    struct Box **p;
  601.  
  602.    struct GadInfo *gad;
  603.  
  604.    if(box->Dim.Kind>0) {
  605.       gad=(struct GadInfo *)box;
  606.       if(gad->SaveTags) free(gad->SaveTags);
  607.       gad->SaveTags=NULL;
  608.  
  609.       if(box->Dim.Kind==STRING_KIND) {
  610.          if(gad->Code) free((void *)gad->Code);
  611.          gad->Code=NULL;
  612.       }
  613.    } else {
  614.  
  615.       if(   (box->Dim.Kind!=GG_VBOX && box->Dim.Kind!=GG_HBOX)
  616.          || !box->Entry) return;
  617.  
  618.       for(p=box->Entry;*p;p++) FreeGuiGadget(*p);
  619.    }
  620. }
  621.  
  622. static void InitGui(struct WinInfo *winfo,struct Box *box)           /**/
  623. {
  624.    struct Box **p;
  625.    struct GadInfo *gad;
  626.  
  627.    int relx=0,rely=0,absx=0,absy=0;
  628.  
  629.    if(box->Dim.Kind==BUTTON_KIND) {
  630.       gad=(struct GadInfo *)box;
  631.  
  632.       if(!(box->Dim.MinCx | box->Dim.MinPx)) {
  633.          box->Dim.MinCx=gad->Text?strlen(gad->Text):1;
  634.          box->Dim.MinPx=4;
  635.       }
  636. #if 0 /* bereits in defaults eingestellt */
  637.       if(!(box->Dim.MinCy | box->Dim.MinPy)) {
  638.          box->Dim.MinCy=1;
  639.          box->Dim.MinPy=4;
  640.       }
  641. #endif
  642.    } else if(box->Dim.Kind==CYCLE_KIND) {
  643.       char **label;
  644.       int len=1;
  645.  
  646.       gad=(struct GadInfo *)box;
  647.  
  648.       if(!(box->Dim.MinCx | box->Dim.MinPx)) {
  649.  
  650.          if(gad->Tags && (label=(char **)GetTagData(GTCY_Labels,NULL,(struct TagItem *)gad->Tags))) {
  651.             char **p;
  652.             int n;
  653.  
  654.             for(p=label;*p;p++) {
  655.                n=strlen(*p);
  656.                if(n>len) len=n;
  657.             }
  658.          }
  659.  
  660.          box->Dim.MinCx=len;
  661.          box->Dim.MinPx=24;
  662.       }
  663.  
  664.    } else if(box->Dim.Kind==MX_KIND) {
  665.       char **label;
  666.       int cnt=0;
  667.  
  668.       gad=(struct GadInfo *)box;
  669.  
  670.       if(!(box->Dim.MinCy | box->Dim.MinPy)) {
  671.  
  672.          if(gad->Tags && (label=(char **)GetTagData(GTMX_Labels,NULL,(struct TagItem *)gad->Tags))) {
  673.             char **p;
  674.             for(p=label;*p;p++) cnt++;
  675.          }
  676.  
  677.          box->Dim.MinCy=cnt;
  678.          box->Dim.MinPy=6;
  679.       }
  680.  
  681.    } else if(box->Dim.Kind==GG_PLAINTEXT_KIND) {
  682.  
  683.       if(!(box->Dim.MinCx|box->Dim.MinPx) || !(box->Dim.MinCy|box->Dim.MinPy)) {
  684.  
  685.          struct GG_ObjectSize size;
  686.          gad=(struct GadInfo *)box;
  687.  
  688.          GG_GfxPrintSize(winfo->Window->RPort,gad->Text,&size);
  689.  
  690.  
  691.          if(!(box->Dim.MinCx | box->Dim.MinPx) || (box->Dim.Flags & GG_FLAG_DEFAULT_WIDTH)) {
  692.             box->Dim.Flags |= GG_FLAG_DEFAULT_WIDTH;
  693.             box->Dim.MinPx=size.Width;
  694.          }
  695.  
  696.          if(!(box->Dim.MinCy | box->Dim.MinPy) || (box->Dim.Flags & GG_FLAG_DEFAULT_HEIGHT)) {
  697.             box->Dim.Flags |= GG_FLAG_DEFAULT_HEIGHT;
  698.             box->Dim.MinPy=size.Height;
  699.          }
  700.       }
  701.    } else if(box->Dim.Kind==GG_GFXBUTTON_KIND) {
  702.  
  703.       if(!(box->Dim.MinCx|box->Dim.MinPx)) {
  704.  
  705.          struct Image *i,*i2;
  706.  
  707.          gad=(struct GadInfo *)box;
  708.          i=(struct Image *)gad->Tags[0];
  709.          i2=(struct Image *)gad->Tags[1];
  710.  
  711.          if(i) box->Dim.MinPx=i->Width;
  712.          if(i2 && i2->Width>i->Width) box->Dim.MinPx=i2->Width;
  713.  
  714.       }
  715.  
  716.       if(!(box->Dim.MinCy|box->Dim.MinPy)) {
  717.  
  718.          struct Image *i,*i2;
  719.  
  720.          gad=(struct GadInfo *)box;
  721.          i=(struct Image *)gad->Tags[0];
  722.          i2=(struct Image *)gad->Tags[1];
  723.  
  724.  
  725.          if(i) box->Dim.MinPy=i->Height;
  726.          if(i2 && i2->Height>i->Height) box->Dim.MinPy=i2->Height;
  727.  
  728.       }
  729.    }
  730.  
  731.    box->Dim.Px+=box->Dim.Cx*winfo->FontX;
  732.    box->Dim.Py+=box->Dim.Cy*winfo->FontY;
  733.  
  734.    box->Dim.MinPx+=box->Dim.MinCx*winfo->FontX;
  735.    box->Dim.MinPy+=box->Dim.MinCy*winfo->FontY;
  736.  
  737.    if(!box->Entry || box->Dim.Kind>0 || box->Dim.Kind==GG_CUSTOM_KIND) {
  738.       return;
  739.    }
  740.  
  741.    for(p=box->Entry;*p;p++) InitGui(winfo,*p);
  742.  
  743.    if(box->Dim.Kind==GG_HBOX) {
  744.  
  745.       for(p=box->Entry;*p;p++) {
  746.          relx+=(*p)->Dim.Rx;
  747.          absx+=(*p)->Dim.Px;
  748.  
  749.          rely=max(rely,(*p)->Dim.Ry);
  750.          absy=max(absy,(*p)->Dim.Py);
  751.       }
  752.    } else {
  753.       for(p=box->Entry;*p;p++) {
  754.          rely+=(*p)->Dim.Ry;
  755.          absy+=(*p)->Dim.Py;
  756.  
  757.          relx=max(relx,(*p)->Dim.Rx);
  758.          absx=max(absx,(*p)->Dim.Px);
  759.       }
  760.    }
  761.  
  762.    if(relx==0) relx=1;
  763.    if(rely==0) rely=1;
  764.  
  765.    box->Dim.SRx=relx;
  766.    box->Dim.SRy=rely;
  767.    box->Dim.SPx=absx;
  768.    box->Dim.SPy=absy;
  769.  
  770.    for(p=box->Entry;*p;p++) {
  771.       box->Dim.Flags|=(*p)->Dim.Flags & GG_FLAG_TRADEMASK;
  772.    }
  773.  
  774.    return;
  775. }          /**/
  776. static void DeInitGui(struct WinInfo *winfo,struct Box *box)           /**/
  777. {
  778.    struct Box **p;
  779.  
  780.    box->Dim.Px-=box->Dim.Cx*winfo->FontX;
  781.    box->Dim.Py-=box->Dim.Cy*winfo->FontY;
  782.  
  783.    box->Dim.MinPx-=box->Dim.MinCx*winfo->FontX;
  784.    box->Dim.MinPy-=box->Dim.MinCy*winfo->FontY;
  785.  
  786.    if(!box->Entry || box->Dim.Kind>0 || box->Dim.Kind==GG_CUSTOM_KIND) {
  787.       return;
  788.    }
  789.  
  790.    for(p=box->Entry;*p;p++) DeInitGui(winfo,*p);
  791.  
  792.    return;
  793. }          /**/
  794. static int BackupGui(struct WinInfo *winfo,struct Box *box)          /**/
  795. {
  796.    struct GadInfo *gad=(struct GadInfo *)box;
  797.    int err=0;
  798.  
  799.    if(box->Dim.Flags & (GG_FLAG_STRING | GG_FLAG_INTEGER)) {
  800.  
  801.       if(box->Dim.Kind==INTEGER_KIND) {
  802.          ULONG tags[]={GTIN_Number,0,TAG_DONE};
  803.          tags[1]=GetNumber(gad->ThisGad);
  804.          MergeTags(gad->SaveTags,tags);
  805. /*         gad->Code=GetNumber(gad->ThisGad); */
  806.       } else if(box->Dim.Kind==STRING_KIND) {
  807.          ULONG tags[]={GTST_String,0,TAG_DONE};
  808.          if(gad->Code) free((void *)gad->Code);
  809.          gad->Code=(ULONG)strdup(GetString(gad->ThisGad));
  810.          if(!gad->Code) return(1);
  811.          tags[1]=gad->Code;
  812.          MergeTags(gad->SaveTags,tags); /* This is always successful, since
  813.                                          * there is always a GTST_String tag
  814.                                          * in the taglist (see MakeGTGadget) */
  815.       } else if(box->Dim.Kind==GG_VBOX || box->Dim.Kind==GG_HBOX) {
  816.          struct Box **p;
  817.  
  818.          if(!box->Entry) return(0);
  819.  
  820.          for(p=box->Entry; *p; p++) {
  821.             err|=BackupGui(winfo,*p);
  822.          }
  823.       }
  824.    }
  825.    return(err);
  826. } /**/
  827. static void FindCustom(struct WinInfo *winfo,struct Box *box)        /**/
  828. {
  829.    struct GadInfo *gad=(struct GadInfo *)box;
  830.    static struct NewGadget ng; /* Just to avoid Enforcer Hits */
  831.  
  832.    if( !(box->Dim.Flags & GG_FLAG_CUSTOM)) return;
  833.  
  834.    if(box->Dim.Kind==GG_CUSTOM_KIND) {
  835.       gad->CustomFunc(winfo,&ng,gad,0,0,0,0);
  836.    } else if(box->Dim.Kind==GG_VBOX || box->Dim.Kind==GG_HBOX) {
  837.       struct Box **p;
  838.  
  839.       if(box->Dim.Flags & GG_FLAG_CUSTOM) {
  840.          if(!box->Entry) return;
  841.  
  842.          for(p=box->Entry; *p; p++) {
  843.             FindCustom(winfo,*p);
  844.          }
  845.       }
  846.    }
  847. } /**/
  848.  
  849. struct IntuiMessage *GG_GetIMsg(struct MsgPort *userport) /**/
  850. {
  851.    struct IntuiMessage *msg;
  852.    int ignore=1;
  853.    struct Gadget *gad;
  854.  
  855.    while(ignore && (msg=GT_GetIMsg(userport))) {
  856.  
  857.       ignore=0;
  858.  
  859.       switch(msg->Class) {
  860.          case IDCMP_MOUSEMOVE:
  861.          case IDCMP_GADGETUP:
  862.          case IDCMP_GADGETDOWN:
  863.             gad=(struct Gadget *)msg->IAddress;
  864.             if(gad && gad->GadgetID>=0) {
  865.                struct GadInfo *gi;
  866.                ULONG tags[]={0,0,TAG_DONE};
  867.                gi=GetInfo(gad);
  868.  
  869.                if(gi->Dim.Kind>=0 && Modify[gi->Dim.Kind]) {
  870.                   tags[0]=Modify[gi->Dim.Kind];
  871.                   tags[1]=msg->Code;
  872.                   MergeTags(gi->SaveTags,tags); /* always successful in this case */
  873.                }
  874.                if(GetInfo(gad)->HookFunc) ignore=GetInfo(gad)->HookFunc(msg);
  875.             }
  876.             break;
  877.       }
  878.       if(ignore) {
  879.          GT_ReplyIMsg(msg);
  880.       }
  881.    }
  882.    return msg;
  883. } /**/
  884.  
  885. void GG_ClearWindow(struct Window *win)
  886. {
  887.    RefreshWindowFrame(win);
  888.    EraseRect(win->RPort,win->BorderLeft,
  889.                         win->BorderTop,
  890.                         win->Width-1-win->BorderRight,
  891.                         win->Height-1-win->BorderBottom);
  892. }
  893.  
  894. int GG_RenderGui(struct Window *win, struct WinInfo *winfo)             /**/
  895. {
  896.    winfo->Window=win;
  897.    winfo->Mode=GG_MODE_NEW;
  898.    winfo->Render=1;
  899.  
  900.    AskFont(win->RPort,&winfo->TextAttr);
  901.  
  902.    winfo->FontX = win->RPort->Font->tf_XSize;
  903.    winfo->FontY = win->RPort->Font->tf_YSize;
  904.    winfo->Visual=GetVisualInfoA(win->WScreen,NULL);
  905.  
  906.    if(!(winfo->Box->Dim.Flags & GG_FLAG_INITED)) {
  907.       winfo->Box->Dim.Flags |= GG_FLAG_INITED;
  908.       InitGui(winfo,winfo->Box);
  909.    }
  910.  
  911.    if(!winfo->Visual) goto exit_fail2;
  912.  
  913.    if(!CreateContext(&winfo->GList)) return(1);
  914.  
  915.    winfo->Prev=winfo->GList;
  916.  
  917.    if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
  918.                      win->Width - win->BorderLeft - win->BorderRight,
  919.                      win->Height - win->BorderTop - win->BorderBottom))
  920.                                                              goto exit_fail3;
  921.    AddGList(win,winfo->GList,-1,-1,NULL);
  922.    RefreshGList(winfo->GList,win,NULL,-1);
  923.    GT_RefreshWindow(win,NULL);
  924.  
  925.    if(winfo->Box->Dim.Flags & GG_FLAG_BACKUP) {
  926.       winfo->Mode=GG_MODE_RESTORE;
  927.       FindCustom(winfo,winfo->Box);
  928.       winfo->Box->Dim.Flags &= ~GG_FLAG_BACKUP;
  929.    }
  930.  
  931.    return(0);
  932.  
  933. exit_fail3:
  934.    if(winfo->GList) FreeGadgets(winfo->GList);
  935.    FreeVisualInfo(winfo->Visual);
  936. exit_fail2:
  937.    return(1);
  938. }  /**/
  939. int GG_ResizeGui(struct WinInfo *winfo)                                 /**/
  940. {
  941.    struct Window *win=winfo->Window;
  942.  
  943.    if(winfo->GList) {
  944.  
  945.       winfo->Box->Dim.Flags|=GG_FLAG_SKIPREFRESH;
  946.       winfo->Mode=GG_MODE_BACKUP;
  947.       winfo->Render=0;
  948.  
  949.       FindCustom(winfo,winfo->Box); /* Backup of customgadgets */
  950.  
  951.       BackupGui(winfo,winfo->Box);
  952.  
  953.       winfo->Mode=GG_MODE_RESIZE;
  954.       winfo->Render=1;
  955.  
  956.       RemoveGList(win,winfo->GList,-1);
  957.       FreeGadgets(winfo->GList);
  958.  
  959.       winfo->GList=NULL;
  960.    }
  961.  
  962.    if(winfo->Box->Backfill==NULL) GG_ClearWindow(win); else RefreshWindowFrame(win);
  963.  
  964.    if(!CreateContext(&winfo->GList)) return(1);
  965.    winfo->Prev=winfo->GList;
  966.  
  967.    if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
  968.                      win->Width - win->BorderLeft - win->BorderRight,
  969.                      win->Height - win->BorderTop - win->BorderBottom))
  970.                                                                   return(2);
  971.  
  972.    AddGList(win,winfo->GList,-1,-1,NULL);
  973.    RefreshGList(winfo->GList,win,NULL,-1);
  974.  
  975.    GT_RefreshWindow(win,NULL);
  976.  
  977.    winfo->Mode=GG_MODE_RESTORE;
  978.    winfo->Render=0;
  979.    FindCustom(winfo,winfo->Box);
  980.  
  981.    return(0);
  982. }  /**/
  983. void GG_BeginResizeGui(struct WinInfo *winfo)
  984. {
  985.    struct Window *win=winfo->Window;
  986.  
  987.    if(winfo->GList) {
  988.  
  989.       winfo->Box->Dim.Flags|=GG_FLAG_SKIPREFRESH;
  990.       winfo->Mode=GG_MODE_BACKUP;
  991.       winfo->Render=0;
  992.  
  993.       FindCustom(winfo,winfo->Box); /* Backup of customgadgets */
  994.  
  995.       BackupGui(winfo,winfo->Box);
  996.  
  997.       winfo->Mode=GG_MODE_RESIZE;
  998.       winfo->Render=1;
  999.  
  1000.       RemoveGList(win,winfo->GList,-1);
  1001.       FreeGadgets(winfo->GList);
  1002.  
  1003.       winfo->GList=NULL;
  1004.    }
  1005. }
  1006.  
  1007. int GG_RefreshGui(struct WinInfo *winfo)                                /**/
  1008. {
  1009.    struct Window *win=winfo->Window;
  1010.  
  1011.    if(winfo->Box->Dim.Flags&GG_FLAG_SKIPREFRESH) {
  1012.       winfo->Box->Dim.Flags&=~GG_FLAG_SKIPREFRESH;
  1013.       return(0);
  1014.    }
  1015.  
  1016.    if(!winfo->GList) return 0;
  1017.  
  1018.    winfo->Render=1;
  1019.    winfo->Mode=GG_MODE_REFRESH;
  1020.    if(MakeGuiGadget(winfo,winfo->Box,win->BorderLeft,win->BorderTop,
  1021.                     win->Width - win->BorderLeft - win->BorderRight,
  1022.                     win->Height - win->BorderTop - win->BorderBottom)) return(1);
  1023.  
  1024.    RefreshGList(winfo->GList,win,NULL,-1);
  1025.    GT_RefreshWindow(winfo->Window,NULL);
  1026.    return 0;
  1027. }         /**/
  1028.  
  1029. static void FreeStopGui(struct WinInfo *winfo,int backup)                       /**/
  1030. {
  1031.    winfo->Render=0;
  1032.    if(backup) {
  1033.       winfo->Mode=GG_MODE_BACKUP;
  1034.       BackupGui(winfo,winfo->Box);
  1035.       FindCustom(winfo,winfo->Box);
  1036.       winfo->Box->Dim.Flags|=GG_FLAG_BACKUP;
  1037.       winfo->Mode=GG_MODE_STOP;
  1038.       FindCustom(winfo,winfo->Box);
  1039.    } else {
  1040.       winfo->Mode=GG_MODE_FREE;
  1041.       FindCustom(winfo,winfo->Box);
  1042.       FreeGuiGadget(winfo->Box);
  1043.    }
  1044.  
  1045.    if(winfo->GList) {
  1046.       RemoveGList(winfo->Window,winfo->GList,-1);
  1047.       FreeGadgets(winfo->GList);
  1048.       winfo->GList=NULL;
  1049.    }
  1050.    if(winfo->Visual) {
  1051.       FreeVisualInfo(winfo->Visual);
  1052.       winfo->Visual=NULL;
  1053.    }
  1054.  
  1055.    if(winfo->Box->Dim.Flags & GG_FLAG_INITED) {
  1056.       winfo->Box->Dim.Flags &= ~GG_FLAG_INITED;
  1057.       DeInitGui(winfo,winfo->Box);
  1058.    }
  1059. } /**/
  1060. void GG_FreeGui(struct WinInfo *winfo)
  1061. {
  1062.    FreeStopGui(winfo,0);
  1063. }
  1064. void GG_StopGui(struct WinInfo *winfo)
  1065. {
  1066.    FreeStopGui(winfo,1);
  1067. }
  1068.  
  1069. static int RenderSubGui(struct WinInfo *winfo,                              /**/
  1070.                  int left,int top,int width, int height)
  1071. {
  1072.    InitGui(winfo,winfo->Box);
  1073.  
  1074.    if(MakeGuiGadget(winfo,winfo->Box,left,top,width,height)) return(1);
  1075.  
  1076.    return(0);
  1077. } /**/
  1078. static int ResizeSubGui(struct WinInfo *winfo,                              /**/
  1079.                  int left, int top,int width,int height)
  1080. {
  1081.    if(MakeGuiGadget(winfo,winfo->Box,left,top,width,height)) return(1);
  1082.  
  1083.    return(0);
  1084. } /**/
  1085. static int RefreshSubGui(struct WinInfo *winfo,int left,int top,int width,int height) /**/
  1086. {
  1087.    winfo->Mode=GG_MODE_REFRESH;
  1088.    return(MakeGuiGadget(winfo,winfo->Box,left,top,width,height));
  1089. } /**/
  1090. static void FreeSubGui(struct WinInfo *winfo)                               /**/
  1091. {
  1092.    winfo->Mode=GG_MODE_FREE;
  1093.    FindCustom(winfo,winfo->Box);
  1094.    FreeGuiGadget(winfo->Box);
  1095.    DeInitGui(winfo,winfo->Box);
  1096. }                                         /**/
  1097. static void StopSubGui(struct WinInfo *winfo)                               /**/
  1098. {
  1099.    winfo->Mode=GG_MODE_STOP;
  1100.    FindCustom(winfo,winfo->Box);
  1101.    DeInitGui(winfo,winfo->Box);
  1102. }                                         /**/
  1103.  
  1104. int GG_SubGui(struct WinInfo *parent, struct WinInfo *winfo,            /**/
  1105.                   int left,int top,int width, int height)
  1106. {
  1107.    int ret=0;
  1108.  
  1109.    memcpy((void *)(((ULONG)winfo)+2*sizeof(void *)),
  1110.           (void *)(((ULONG)parent)+2*sizeof(void *)),
  1111.           sizeof(struct WinInfo)-2*sizeof(void *));
  1112.  
  1113.    switch(parent->Mode) {
  1114.  
  1115.       case GG_MODE_NEW:  ret=RenderSubGui(winfo,left,top,width,height);
  1116.                          winfo->Box->Dim.Flags&=~GG_FLAG_BACKUP;
  1117.                          break;
  1118.       case GG_MODE_RESIZE:
  1119.                          ret=ResizeSubGui(winfo,left,top,width,height);
  1120.                          winfo->Box->Dim.Flags&=~GG_FLAG_BACKUP;
  1121.                          break;
  1122.       case GG_MODE_REFRESH:
  1123.                          ret=RefreshSubGui(winfo,left,top,width,height);
  1124.                          break;
  1125.       case GG_MODE_STOP: StopSubGui(winfo);
  1126.                          break;
  1127.       case GG_MODE_FREE: FreeSubGui(winfo);
  1128.                          break;
  1129.       case GG_MODE_RESTORE:
  1130.                          FindCustom(winfo,winfo->Box);
  1131.                          break;
  1132.       case GG_MODE_BACKUP:
  1133.                          ret=BackupGui(winfo,winfo->Box);
  1134.                          FindCustom(winfo,winfo->Box);
  1135.                          winfo->Box->Dim.Flags|=GG_FLAG_BACKUP;
  1136.                          break;
  1137.    }
  1138.    parent->Prev=winfo->Prev;
  1139.    return(ret);
  1140. }  /**/
  1141. static void GetMinSize(struct WinInfo *winfo,                      /**/
  1142.                           struct Box *box,
  1143.                           struct GG_ObjectSize *size)
  1144. {
  1145.    struct Box **p;
  1146.    int relx,rely,absx,absy;
  1147.    int w,h;
  1148.  
  1149.  
  1150.    if(box->Dim.Kind>0 || box->Dim.Kind<=GG_CUSTOM_KIND) {
  1151.  
  1152.       size->Width=box->Dim.MinPx+box->Dim.XSpace;
  1153.       size->Height=box->Dim.MinPy+box->Dim.YSpace;
  1154.  
  1155.       if(!box->Dim.Rx) size->Width=box->Dim.Px;
  1156.       if(!box->Dim.Ry) size->Height=box->Dim.Py;
  1157.  
  1158.    } else {
  1159.  
  1160.       struct GG_ObjectSize osize;
  1161.       int rwidth,rheight;
  1162.  
  1163.       size->Width=size->Height=0;
  1164.  
  1165.       if(!box->Entry) return;
  1166.       if(box->Dim.Flags & GG_FLAG_BAR) return; /* wird bereits beim Init berücksichtigt */
  1167.  
  1168.       /* Sonderbehandlung, falls explizit angegeben */
  1169.  
  1170.       if((box->Dim.MinCx|box->Dim.MinPx) && (box->Dim.MinCy|box->Dim.MinPy)) {
  1171.          size->Width=box->Dim.MinPx+box->Dim.XSpace;
  1172.          size->Height=box->Dim.MinPy+box->Dim.YSpace;
  1173.          return;
  1174.       }
  1175.  
  1176.  
  1177.       if(!box->Dim.Rx && !box->Dim.Ry) {
  1178.          size->Width=box->Dim.Px;
  1179.          size->Height=box->Dim.Py;
  1180.          return;
  1181.       }
  1182.  
  1183.       relx=box->Dim.SRx;
  1184.       rely=box->Dim.SRy;
  1185.       absx=box->Dim.SPx;
  1186.       absy=box->Dim.SPy;
  1187.  
  1188.       if(box->Dim.Kind==GG_HBOX) {
  1189.  
  1190.          rheight=absy;
  1191.          rwidth=0;
  1192.  
  1193.          for(p=box->Entry;*p;p++) {
  1194.  
  1195.             if((*p)->Dim.Rx || (*p)->Dim.Ry) GetMinSize(winfo,*p,&osize);
  1196.  
  1197.             if((*p)->Dim.Rx) {
  1198.                w=(osize.Width+(*p)->Dim.Rx-1)/(*p)->Dim.Rx*relx;
  1199.                rwidth=max(rwidth,w);
  1200.             }
  1201.  
  1202.             if((*p)->Dim.Ry) {
  1203.                h=(osize.Height+(*p)->Dim.Ry-1)/(*p)->Dim.Ry*rely;
  1204.                rheight=max(rheight,h);
  1205.             }
  1206.          }
  1207.  
  1208.          size->Width=rwidth+absx;
  1209.          size->Height=rheight;
  1210.       } else {
  1211.  
  1212.          rheight=0;
  1213.          rwidth=absx;
  1214.  
  1215.          for(p=box->Entry;*p;p++) {
  1216.  
  1217.             if((*p)->Dim.Rx || (*p)->Dim.Ry) GetMinSize(winfo,*p,&osize);
  1218.  
  1219.             if((*p)->Dim.Ry) {
  1220.                h=(osize.Height+(*p)->Dim.Ry-1)/(*p)->Dim.Ry*rely;
  1221.                rheight=max(rheight,h);
  1222.             }
  1223.  
  1224.             if((*p)->Dim.Rx) {
  1225.                w=(osize.Width+(*p)->Dim.Rx-1)/(*p)->Dim.Rx*relx;
  1226.                rwidth=max(rwidth,w);
  1227.             }
  1228.          }
  1229.  
  1230.          size->Width=rwidth;
  1231.          size->Height=rheight+absy;
  1232.       }
  1233.  
  1234.       if(box->Dim.Flags & (GG_FLAG_RAISED | GG_FLAG_RECESSED)) {
  1235.  
  1236.          size->Width+=2*box->Dim.XSpace;
  1237.          size->Height+=2*box->Dim.YSpace;
  1238.       }
  1239.  
  1240.       /* Explizit angegebene Werte überschreiben berechnete */
  1241.  
  1242.       if(box->Dim.MinCx|box->Dim.MinPx) size->Width=box->Dim.MinPx+box->Dim.XSpace;
  1243.       if(box->Dim.MinCy|box->Dim.MinPy) size->Height=box->Dim.MinPy+box->Dim.YSpace;
  1244.  
  1245.       if(!box->Dim.Rx) size->Width=box->Dim.Px;
  1246.       if(!box->Dim.Ry) size->Height=box->Dim.Py;
  1247.    }
  1248.  
  1249.    return;
  1250. }          /**/
  1251.  
  1252. void GG_MinSize(struct Window *win, struct WinInfo *winfo,struct GG_ObjectSize *size)
  1253. {
  1254.    int inited=0;
  1255.    struct Window *oldwin;
  1256.  
  1257.    oldwin=winfo->Window;
  1258.  
  1259.    if(winfo->Box->Dim.Flags & GG_FLAG_INITED) {
  1260.       inited=1;
  1261.       if(winfo->Window!=win) {
  1262.          DeInitGui(winfo,winfo->Box);
  1263.          winfo->Window=win;
  1264.          winfo->FontX = winfo->Window->RPort->Font->tf_XSize;
  1265.          winfo->FontY = winfo->Window->RPort->Font->tf_YSize;
  1266.          InitGui(winfo,winfo->Box);
  1267.       }
  1268.    } else {
  1269.       winfo->Window=win;
  1270.       winfo->FontX = winfo->Window->RPort->Font->tf_XSize;
  1271.       winfo->FontY = winfo->Window->RPort->Font->tf_YSize;
  1272.       InitGui(winfo,winfo->Box);
  1273.    }
  1274.  
  1275.    GetMinSize(winfo,winfo->Box,size);
  1276.  
  1277.    if(inited) {
  1278.       if(oldwin!=winfo->Window) {
  1279.          DeInitGui(winfo,winfo->Box);
  1280.          winfo->Window=oldwin;
  1281.          winfo->FontX = winfo->Window->RPort->Font->tf_XSize;
  1282.          winfo->FontY = winfo->Window->RPort->Font->tf_YSize;
  1283.          InitGui(winfo,winfo->Box);
  1284.       }
  1285.    } else {
  1286.       DeInitGui(winfo,winfo->Box);
  1287.    }
  1288. }
  1289. void GG_MinSizeFont(struct TextFont *font,struct WinInfo *winfo,struct GG_ObjectSize *size)
  1290. {
  1291.    struct Window win;
  1292.    struct RastPort rp;
  1293.  
  1294.    win.RPort=&rp;
  1295.    InitRastPort(&rp);
  1296.  
  1297.    SetFont(&rp,font);
  1298.  
  1299.    GG_MinSize(&win,winfo,size);
  1300.    return;
  1301. }
  1302.  
  1303. static struct TextAttr topaz={
  1304.    "topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT};
  1305.  
  1306. int GG_SmartRenderGui(struct Window *win, struct WinInfo *winfo,struct TextFont **font)
  1307. {
  1308.    struct GG_ObjectSize size;
  1309.    int left,top,width,height;
  1310.    ULONG idcmp;
  1311.    short changed;
  1312.  
  1313.    GG_MinSize(win,winfo,&size);
  1314.  
  1315.    size.Width+=win->BorderLeft+win->BorderRight;
  1316.    size.Height+=win->BorderTop+win->BorderBottom;
  1317.  
  1318.    if(size.Width>win->WScreen->Width || size.Height>win->WScreen->Height) {
  1319.  
  1320.       if(*font || (*font=OpenFont(&topaz))) {
  1321.          SetFont(win->RPort,*font);
  1322.       }
  1323.  
  1324.       GG_MinSize(win,winfo,&size);
  1325.       size.Width+=win->BorderLeft+win->BorderRight;
  1326.       size.Height+=win->BorderTop+win->BorderBottom;
  1327.    }
  1328.  
  1329.    if(size.Width>win->WScreen->Width) size.Width=win->WScreen->Width;
  1330.    if(size.Height>win->WScreen->Height) size.Height=win->WScreen->Height;
  1331.  
  1332.  
  1333.    Forbid();
  1334.  
  1335.    if(size.Width<=win->Width && size.Height<=win->Height) {
  1336.  
  1337.       /* Window is large enough, just set Windowlimits */
  1338.  
  1339.       WindowLimits(win,size.Width,size.Height,-1,-1);
  1340.       Permit();
  1341.       return GG_RenderGui(win,winfo);
  1342.    }
  1343.  
  1344.    Permit();
  1345.  
  1346.  
  1347.    /* Calculate the new window-dimensions */
  1348.  
  1349.    left=win->LeftEdge;
  1350.    top=win->TopEdge;
  1351.    width=win->Width;
  1352.    height=win->Height;
  1353.  
  1354.    if(size.Width>width) width=size.Width;
  1355.    if(size.Height>height) height=size.Height;
  1356.    if(left+width>win->WScreen->Width) left=win->WScreen->Width-width;
  1357.    if(top+height>win->WScreen->Height) top=win->WScreen->Height-height;
  1358.  
  1359.    idcmp=win->IDCMPFlags;
  1360.    if(!ModifyIDCMP(win,(idcmp|IDCMP_CHANGEWINDOW) & ~IDCMP_NEWSIZE))
  1361.             return 1; /* Could not Modify IDCMP */
  1362.  
  1363.    ChangeWindowBox(win,left,top,width,height);
  1364.  
  1365.    changed=0;
  1366.  
  1367.    while(!changed) { /* Wait until the window has changed it dimensions, */
  1368.                      /* but keep all other Messages                      */
  1369.  
  1370.       struct IntuiMessage *msg,*succ;
  1371.  
  1372.       Wait(1<<win->UserPort->mp_SigBit);
  1373.  
  1374.       Forbid();
  1375.  
  1376.       for(msg=(struct IntuiMessage *) win->UserPort->mp_MsgList.lh_Head;
  1377.             (succ=(struct IntuiMessage *)msg->ExecMessage.mn_Node.ln_Succ)
  1378.                && !changed; msg=succ) {
  1379.  
  1380.          if(msg->IDCMPWindow==win && msg->Class==IDCMP_CHANGEWINDOW) {
  1381.  
  1382.             Remove((struct Node *)msg);
  1383.             ReplyMsg((struct Message *)msg);
  1384.             changed=1;
  1385.          }
  1386.       }
  1387.  
  1388.       Permit();
  1389.    }
  1390.  
  1391.    ModifyIDCMP(win,idcmp);
  1392.    WindowLimits(win,size.Width,size.Height,-1,-1);
  1393.  
  1394.    /* The next refresh is caused by IDCMP_CHANGEWINDOW. Since the
  1395.       GUI was not rendered yet, we may skip it */
  1396.  
  1397.    winfo->Box->Dim.Flags|=GG_FLAG_SKIPREFRESH;
  1398.    return GG_RenderGui(win,winfo);
  1399. }
  1400.  
  1401.  
  1402.  
  1403.